﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;

namespace MyAssetBundles {
    public class PackFolderProgress : FolderProgress {
        protected override void ShowProgress ()
        {
            string info = string.Format("process number: {0}k, total number: {1}k, progress: {2}%", target.processNum / 1000, target.totalNum / 1000, target.progress * 100);
            ShowProgress("Pack", info);
        }
    }

    public class PackFolder : BaseFolder, IFolder {
        public long _packageSize;
        public void Generate (string path, IFolderProgress progress)
        {
            Dictionary<string, MyFileInfo> contrastDic = new Dictionary<string, MyFileInfo>();
            foreach (var item in this)
            {
                if (item.Value.IsContrast)
                    contrastDic.Add(item.Key, item.Value);
            }
            if (contrastDic.Count == 0) return;

            int singleDesByteNum = 4 + 4 + 4 + 4 + 4 + 4;
            int desByteNum = 4 + 4 + singleDesByteNum * contrastDic.Count;
            int fileByteNum = desByteNum;
            Dictionary<string, MyFileInfo>.Enumerator etor = contrastDic.GetEnumerator();
            while (etor.MoveNext())
            {
                etor.Current.Value.NameCursorStart = fileByteNum;
                fileByteNum += etor.Current.Value.NameByte.Length;

                etor.Current.Value.MD5CursorStart = fileByteNum;
                fileByteNum += etor.Current.Value.MD5Byte.Length;
            }

            etor = contrastDic.GetEnumerator();
            while (etor.MoveNext())
            {
                etor.Current.Value.DataCursorStart = fileByteNum;
                fileByteNum += etor.Current.Value.DataByteLength;
            }

            byte[] fileDes = new byte[desByteNum]; int offset = 8;
            Array.Copy(BitConverter.GetBytes(contrastDic.Count), 0, fileDes, 0, 4);
            Array.Copy(BitConverter.GetBytes(singleDesByteNum), 0, fileDes, 4, 4);
            etor = contrastDic.GetEnumerator();
            while (etor.MoveNext())
            {
                MyFileInfo myFile = etor.Current.Value;
                Array.Copy(BitConverter.GetBytes(myFile.NameCursorStart), 0, fileDes, offset, 4);
                Array.Copy(BitConverter.GetBytes(myFile.NameByte.Length), 0, fileDes, offset + 4, 4);
                Array.Copy(BitConverter.GetBytes(myFile.MD5CursorStart), 0, fileDes, offset + 8, 4);
                Array.Copy(BitConverter.GetBytes(myFile.MD5Byte.Length), 0, fileDes, offset + 12, 4);
                Array.Copy(BitConverter.GetBytes(myFile.DataCursorStart), 0, fileDes, offset + 16, 4);
                Array.Copy(BitConverter.GetBytes(myFile.DataByteLength), 0, fileDes, offset + 20, 4);
                offset += singleDesByteNum;
            }

            FileInfo file = new FileInfo(path);
            FileStream fStream = file.Create();
            fStream.Write(fileDes, 0, fileDes.Length);
            etor = contrastDic.GetEnumerator();
            while (etor.MoveNext())
            {
                fStream.Write(etor.Current.Value.NameByte, 0, etor.Current.Value.NameByte.Length);
                fStream.Write(etor.Current.Value.MD5Byte, 0, etor.Current.Value.MD5Byte.Length);
            }

            int writeByteNum = 0, totalByteNum = fileByteNum - (int)fStream.Length;
            SetProgress(progress, totalByteNum);
            byte[] content = new byte[1024];
            etor = contrastDic.GetEnumerator();
            while (etor.MoveNext())
            {
                FileStream readFile = new FileStream(etor.Current.Value.Path, FileMode.Open, FileAccess.Read);
                int residue = (int)readFile.Length;
                while (residue > 0)
                {
                    int readNum = readFile.Read(content, 0, 1024);
                    fStream.Write(content, 0, readNum);
                    residue -= readNum;
                    writeByteNum += readNum;
                    SetProcessNum(writeByteNum);
                }
                readFile.Close();
            }

            _packageSize = fStream.Length;
            fStream.Flush();
            fStream.Close();
        }
    }
}

